SaveToClipBoard(hwnd, closePaste := false) {
  if hwnd {                                      ; if hwnd is 0, use window
    g := GuiFromHwnd(hwnd)
    g.GetPos(, , &w, &h)
    if g.HasOpt('Border') {
      BMPFromHwnd(&hBitmap, g.Hwnd, w, h, -1, -1)
    } else
      BMPFromHwnd(&hBitmap, g.Hwnd, w, h, 0, 0)
    if closePaste
      g.Destroy()
  } else {
    w := A_ScreenWidth, h := A_ScreenHeight
    BMPFromHwnd(&hBitmap, hwnd, w, h, 0, 0)
    logger.Info('截全屏到剪贴板')
  }
  DllCall("OpenClipboard", "Ptr", 0)
  DllCall("EmptyClipboard")
  DllCall("SetClipboardData", "uint", 2, "Ptr", hBitmap)
  DllCall("CloseClipboard")
  DllCall("DeleteObject", "Ptr", hBitmap)
  Tip.ShowTip('已存入喵~', , , , false)
}

SaveToFileEx(hwnd, path := unset, fileName := unset, closePaste := false) {
  WinSetAlwaysOnTop(0, 'ahk_id' hwnd)
  IsSet(fileName) || fileName := Meta.name '_' FormatTime(, "yyyyMMdd_HHmmss") '.bmp'
  fullPath := IsSet(path)
    ? path '\' fileName
    : FileSelect("S", cfg.defaultSavePath '\' fileName, '图像另存为', '(*.bmp)')
  WinSetAlwaysOnTop(1, 'ahk_id' hwnd)
  if !fullPath
    return
  g := GuiFromHwnd(hwnd)
  g.GetPos(, , &w, &h)
  if g.HasOpt('Border') {
    BMPFromHwnd(&bmp, g.Hwnd, w, h, -1, -1)
  } else
    BMPFromHwnd(&bmp, g.Hwnd, w, h, 0, 0)
  if closePaste
    WinClose('ahk_id' hwnd)
  SaveToFile(bmp, fullPath)
  return fullPath
}

SaveToFile(BMP, fullPath) {
  GetBitmapWH(BMP, &bw, &bh)
  tmp := CreateDIBSection(bw, bh)
  CopyHBM(tmp, BMP, bw, bh, 0, 0, 0, 0)
  DllCall("DeleteObject", "ptr", BMP)
  BMP := tmp
  buf := Buffer(sobuf := (A_PtrSize = 8 ? 104 : 84))
  DllCall("GetObject"
    , "ptr", BMP
    , "int", sobuf
    , "ptr", buf)
  bfh := buf.Ptr + (A_PtrSize = 8 ? 32 : 24)
  size := NumGet(bfh + 20, 'uint')
  pBits := NumGet(bfh - A_PtrSize, 'ptr')
  bf := Buffer(14, 0)
  NumPut('short', 0x4D42, bf)
  NumPut('uint', size + 54, bf, 2)
  NumPut('uint', 54, bf, 10)
  try {
    f := FileOpen(fullPath, "w")
    f.RawWrite(bf, 14)
    f.RawWrite(bfh, 40)
    f.RawWrite(pBits, size)
    f.Close()
    Tip.ShowTip('成功保存到文件喵~', , , , false)
  } catch as e {
    logger.Warn('无法保存为文件，消息：' e.Message)
    MsgBox(A_ThisFunc, e.Message)
  } finally {
    DllCall("DeleteObject", "ptr", BMP)
    logger.Info('保存为文件，路径：' fullPath)
  }
}